package org.beanutopia.reflect;

import com.google.common.base.Nullable;

/**
 * @author ymeymann
 * @since Nov 21, 2007 11:49:46 PM
 */
public class Reflector<V> {

  //TODO static cache of readers/writers/reflectors instead of cache within Getter and Setter
  //TODO somehow cache negative result of method searching  

  /* readers */
  public static <V> GetMethod<V> reader(String propertyName) {
    return reader(null, propertyName, "get");
  }

  public static <V> GetMethod<V> reader(String propertyName, @Nullable String getterPrefix) {
    return reader(null, propertyName, getterPrefix);
  }

  public static <V> GetMethod<V> reader(@Nullable Class objectClass, String propertyName) {
    return reader(objectClass, propertyName, "get");
  }

  public static <V> GetMethod<V> reader(@Nullable Class objectClass, String propertyName, String getterPrefix) {
    return reader(objectClass, propertyName, null, getterPrefix);
  }

  public static <V> GetMethod<V> reader(@Nullable Class objectClass, String propertyName, @Nullable Class<V> valueClass, String getterPrefix) {
    return new Getter<V>(objectClass, propertyName, valueClass, getterPrefix);
  }

  /* writers */
  public static <V> SetMethod<V> writer(String propertyName) {
    return writer(propertyName, "set");
  }

  public static <V> SetMethod<V> writer(String propertyName, @Nullable String setterPrefix) {
    return writer(null, propertyName, null, setterPrefix);
  }

  public static <V> SetMethod<V> writer(@Nullable Class objectClass, String propertyName, @Nullable Class<V> valueClass) {
    return writer(objectClass, propertyName, valueClass, "set");
  }

  public static <V> SetMethod<V> writer(@Nullable Class objectClass, String propertyName, @Nullable Class<V> valueClass,
                   @Nullable String setterPrefix) {
    return new Setter<V>(objectClass, propertyName, valueClass, setterPrefix);
  }

  public static String buildMethodName(String propertyName, String prefix) {
    return (prefix != null && prefix.length() > 0) ?
            prefix + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1) :
            propertyName;
  }


}
